﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace IFT.Classes
{
  #region PlayerEnums
  public enum PlayerRole
  {
    RoleAttacker,
    RoleDefender
  }
  #endregion PlayerEnums

  class Player
  {
    private SortedList<int, int> m_reserve            = new SortedList<int, int>();
    private SortedList<UnitType, CombatLine> m_field  = new SortedList<UnitType, CombatLine>();
    private Battlefield m_battlefield                 = null;
    private PlayerRole m_role                         = PlayerRole.RoleAttacker;

    #region PlayerPropertys
    public Battlefield BattleField
    {
      get { return m_battlefield; }
    }

    public PlayerRole Role
    {
      get { return m_role; }
      set { m_role = (PlayerRole)value; }
    }

    public Player Enemy
    {
      get { return (m_battlefield.Attacker == this) ? m_battlefield.Defender : m_battlefield.Attacker; }
    }
    #endregion PlayerPropertys

    public Player() { }

    public Player(Battlefield BattlefieldOwner)
    {
      m_battlefield = BattlefieldOwner;

      for (UnitType unitType = UnitType.MinUnitFieldType + 1; unitType < UnitType.MaxUnitFieldType; unitType++)
        m_field.Add(unitType, new CombatLine(this, unitType));
    }

    public int GetReserveCount(int unitId) { return (m_reserve.ContainsKey(unitId)) ? m_reserve[unitId] : -1; }
    public void SetReserveCount(int unitId, int count) { if (m_reserve.ContainsKey(unitId)) m_reserve[unitId] = count; }

    public bool HasUnitOnField(int unitId)
    {
      for (UnitType i = UnitType.MinUnitFieldType + 1; i < UnitType.MaxUnitFieldType; i++)
      {
        if (m_field[i].HasUnit(unitId))
          return true;
      }

      return false;
    }

    public bool HasUnitOnField(UnitType unitType)
    {
      for (UnitType i = UnitType.MinUnitFieldType + 1; i < UnitType.MaxUnitFieldType; i++)
      {
        if (m_field[i].HasUnit(unitType))
          return true;
      }

      return false;
    }

    public bool HasUnitOnReserve(int unitId)
    {
      return (GetReserveCount(unitId) > 0) ? true : false;
    }

    public bool HasUnitOnReserve(UnitType unitType)
    {
      XMLUnit unit = null;

      foreach (int key in m_reserve.Keys)
      {
        unit = UnitManager.Instance.GetUnit(key);
        if (unit.Type == unitType && m_reserve[key] > 0)
          return true;
      }

      return false;
    }

    public bool AddUnit(int unitId, int avaibleUnits)
    {
      if (avaibleUnits <= 0 || !UnitManager.Instance.UnitExists(unitId))
        return false;

      if (!HasUnitOnReserve(unitId))
        m_reserve.Add(unitId, avaibleUnits);
      else
        SetReserveCount(unitId, avaibleUnits);

      return true;
    }

    public void EndRound()
    {
      foreach (KeyValuePair<UnitType, CombatLine> line in m_field)
      {
        foreach (Unit unit in line.Value)
        {
          if (unit.IsLoaded())
            unit.EndRound();
        }
      }
    }

    public CombatLine GetField(UnitType utype)
    {
      CombatLine line = null;
      m_field.TryGetValue(utype, out line);
      return line;
    }

    public void Init(Battlefield newBattlefield)
    {
      if (m_reserve.Count > 0)
      {

      }
    }

    public void FillAllFieldLines()
    {
      for (UnitType i = UnitType.MinUnitFieldType + 1; i < UnitType.MaxUnitFieldType; i++)
        m_field[i].FillLine();
    }

    public XMLUnit GetNextUnitOnReserve(UnitType unitType, bool allowAlternativeUnit = false)
    {
      XMLUnit NextUnit = null;
      XMLUnit unit = null;

      foreach (int unitId in m_reserve.Keys)
      {
        unit = UnitManager.Instance.GetUnit(unitId);

        if (unit.Type == unitType)
          continue;

        switch (unitType)
        {
          case UnitType.Artillery:
          case UnitType.Bomber:
          case UnitType.LongRange:
          case UnitType.AirDefense:
            {
              if (NextUnit == null || NextUnit.Stats.Damage < unit.Stats.Damage)
                NextUnit = unit;
            } break;
          case UnitType.LightInfantry:
          case UnitType.HeavyInfantry:
            {
              if (NextUnit == null || NextUnit.Stats.Hitpoints > unit.Stats.Hitpoints)
                NextUnit = unit;
            } break;
          default:
            {
              if (NextUnit == null || NextUnit.Stats.Level < unit.Stats.Level)
                NextUnit = unit;
            } break;
        }
      }

      //Find alternative Unit for the FrontLine
      if (allowAlternativeUnit && unitType == UnitType.HeavyInfantry && NextUnit == null)
      {
        NextUnit = GetNextUnitOnReserve(UnitType.LightInfantry);

        if (NextUnit == null)
          NextUnit = GetNextUnitOnReserve(UnitType.LongRange);
      }

      return NextUnit;
    }
  }
}